//
//  CellFooterLayout.swift
//  MagicalCalendar
//
//  Created by CSS on 6/17/23.
//

import UIKit

@objc(CSCellFooterLayout)
class CellFooterLayout: UICollectionViewFlowLayout {

    private var footIndexs: [ Int:Int ] = [:]
    
    private var footIndexOffsets: [ Int:CGFloat ] = [:]
    private var footHeights: [ Int:CGFloat ] = [:]
    
    @objc public var flowlayoutDelegate: UICollectionViewDelegateFlowLayout?
    
    public var missingFooterAttributes: [UICollectionViewLayoutAttributes] = []
    
    override func prepare() {
        super.prepare()
        footHeights.removeAll()
        missingFooterAttributes.removeAll()
    }
    
    /**
     排布rect范围内的控件
     */
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let attributes = super.layoutAttributesForElements(in: rect) else {
            return nil
        }
        
        let newAttributes = attributes.map({ $0.copy() as! UICollectionViewLayoutAttributes })
        var footerAttributes: [UICollectionViewLayoutAttributes] = []
        for attribute in newAttributes {
            let indexPath = attribute.indexPath
            if attribute.representedElementCategory != .cell {
                if let kind = attribute.representedElementKind, kind == UICollectionView.elementKindSectionFooter {
                    footerAttributes.append(attribute)
                    continue
                }
                continue
            }
            if let footIndex = footIndexs[indexPath.section] {
                if indexPath.row == footIndex {
                    footIndexOffsets[indexPath.section] = attribute.frame.maxY
                }
            }
            attribute.frame.origin.y += offset(forFrame: attribute.frame, inSection: indexPath.section)
        }
        
        var hasChangeSections: [Int] = []
        for footerAttribute in footerAttributes {
            footerAttribute.frame.origin.y = footIndexOffsets[footerAttribute.indexPath.section] ?? 0
            hasChangeSections.append(footerAttribute.indexPath.section)
            missingFooterAttributes.append(footerAttribute.copy() as! UICollectionViewLayoutAttributes)
            footerAttribute.size.height = 0
        }
        for (section, footerOffset) in footIndexOffsets {
            if hasChangeSections.contains(section) {
                continue
            }
            if let footerAttribute = layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, at: .init(row: 0, section: section)) {
                footerAttribute.frame.origin.y = footerOffset
                missingFooterAttributes.append(footerAttribute.copy() as! UICollectionViewLayoutAttributes)
            }
        }
        
        return newAttributes
    }
    
    private func offset(forFrame frame: CGRect, inSection: Int) -> CGFloat {
        guard let cellOffset = footIndexOffsets[inSection] else {
            return 0
        }
        if frame.minY < cellOffset {
            return 0
        }
        return footerHeight(forSection: inSection)
    }
    
    private func footerHeight(forSection section: Int) -> CGFloat {
        if let footerHeight = footHeights[section] {
            return footerHeight
        }
        if let collectionView = collectionView {
            let footHeight = (flowlayoutDelegate?.collectionView?(collectionView, layout: self, referenceSizeForFooterInSection: section))?.height ?? 0
            footHeights[section] = footHeight
        }
        return footHeights[section] ?? 0
    }
    
}

// MARK: 对外访问方法
extension CellFooterLayout {
    
    //针对OC写的方法
    //移除该分区
    @objc public func setFooterForCell(inSection: Int) {
        setFooterForCell(atRow: nil, inSection: inSection)
    }
    //增加该分区
    @objc public func setFooterForCell(atIndexPath indexPath: IndexPath) {
        setFooterForCell(atRow: indexPath.row, inSection: indexPath.section)
    }
    
    public func setFooterForCell(atRow row: Int?, inSection: Int) {
        guard let row = row else {
            footIndexs.removeValue(forKey: inSection)
            footHeights.removeValue(forKey: inSection)
            invalidateLayout()
            return
        }
        footIndexs[inSection] = row
        invalidateLayout()
    }
    
    @objc public func resetCellFooters() {
        if footIndexs.isEmpty {
            return
        }
        footIndexs.removeAll()
        invalidateLayout()
    }
    
}
